package cn.yjh.server.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @author yW0041229
 * @since 2021/12/16 10:40
 */
public class MasterReactor extends DefaultDispatcher implements Runnable {

    Logger logger = LoggerFactory.getLogger(MasterReactor.class);

    private Selector selector;

    private ServerSocketChannel serverChannel;

    private int port;


    public MasterReactor(int port,String scanPackage) {
        this.port = port;
        try {
            // 打开一个 Selector
            selector = Selector.open();

            // 建立一个 Server 端通道
            serverChannel = ServerSocketChannel.open();

            // 绑定服务端口
            serverChannel.bind(new InetSocketAddress(port));

            // 设置为非阻塞模式的
            serverChannel.configureBlocking(false);

            // 将 Channel 注册到 Selector，并且 Selector 关注建立连接就绪事件，
            SelectionKey sk = serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            // 给 SelectionKey 绑定附件对象
            sk.attach(new Acceptor(serverChannel, scanPackage));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        logger.info("the main reactor RPC server is starting at port [ {} ]", port);
        try {
            while (!Thread.interrupted()) {

                // 监听就绪事件
                if (selector.select() == 0) {
                    continue;
                }

                // 遍历所有的就绪事件
                Set selected = selector.selectedKeys();
                Iterator it = selected.iterator();
                while (it.hasNext()) {
                    // 进行事件分配
                    this.dispatch((SelectionKey) (it.next()));
                    it.remove();
                }
                selected.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
